import axios from "axios"
import type { AxiosResponse, InternalAxiosRequestConfig } from "axios"
import { ElLoading, ElMessage } from "element-plus"
import { proxyReplace } from "./proxyReplace"
import pinia from "@/stores"
import { useUserInfo } from "@/stores/userInfo"
import router from "@/router"

class AxiosService {
  private loading: any
  private ajaxCount = 0
  private userInfo
  public instance: any

  constructor() {
    this.userInfo = useUserInfo(pinia)
    this.instance = this.setupAxios()
  }

  private setupAxios() {
    const instance = axios.create({
      withCredentials: true,
      timeout: 5 * 1000
    })
    instance.interceptors.request.use(this.requestInterceptor.bind(this), (error) =>
      Promise.reject(error)
    )

    instance.interceptors.response.use(
      this.responseInterceptor.bind(this),
      this.errorInterceptor.bind(this)
    )

    return instance
  }

  private requestInterceptor(config: InternalAxiosRequestConfig) {
    if (!config.annotation?.noLoading) {
      this.loading = ElLoading.service({
        lock: true,
        text: "加载中...",
        background: "rgba(0, 0, 0, 0.7)"
      })
    }
    this.ajaxCount++
    config.url && (config.url = proxyReplace(config.url))
    if (config.annotation?.isVerify) {
      config.headers["Authorization"] = this.userInfo.info.detail?.token || ""
    }
    // 解决get请求缓存问题
    if (config.method && config.method.toLowerCase() === "get") {
      config.params = {
        ...config.params,
        t_t: new Date().getTime()
      }
    }
    return config
  }

  private responseInterceptor(response: AxiosResponse) {
    if (this.loading) {
      this.loading.close()
    }
    if (this.ajaxCount > 0) {
      this.ajaxCount--
    }
    const { status, data } = response
    if (status >= 200 && status < 300) {
      if (data.code === 401) {
        this.userInfo.setInfo({})
        router.push("/login")
        return Promise.reject(data.msg)
      }
      if (data.code !== 200 && data.code !== 401) {
        if (this.ajaxCount === 0) ElMessage.error(data.msg)
        return Promise.reject(data.msg)
      }
      return Promise.resolve(data)
    } else {
      if (this.ajaxCount === 0) ElMessage.error(data.msg || "请求信息错误")
      return Promise.reject(data.msg)
    }
  }

  private errorInterceptor(error: any) {
    if (this.loading) {
      this.loading.close()
    }
    if (this.ajaxCount > 0) {
      this.ajaxCount--
    }
    if (error.response) {
      let msg
      switch (error.response.status) {
        case 403:
          msg = "登录信息已过期,请重新登录"
          break
        case 404:
          msg = "接口请求不存在!错误码【404】。"
          break
        case 500:
          msg = error.response.data.message || "服务端应用接口异常!错误码【500】。"
          break
        default:
          msg = "请求错误，请检查或刷新重试！"
          break
      }
      if (this.ajaxCount === 0) ElMessage.error(msg)
    } else {
      if (this.ajaxCount === 0) ElMessage.error("服务不可用")
    }
    return Promise.reject(error)
  }

  public get(url: string, params?: any, isVerify = false, noLoading = false) {
    const annotation: Record<string, any> = {}
    noLoading && (annotation.noLoading = noLoading)
    isVerify && (annotation.isVerify = isVerify)
    return this.instance.get(url, { params, annotation })
  }

  public post(url: string, data: any, isVerify = false, noLoading = false, isFormData = false) {
    const annotation: Record<string, any> = {}
    noLoading && (annotation.noLoading = noLoading)
    isVerify && (annotation.isVerify = isVerify)
    return this.instance.post(url, data, {
      annotation,
      headers: {
        "Content-Type": isFormData ? "multipart/form-data" : "application/json"
      }
    })
  }

  // 获取实例
  public getInstance() {
    return this.instance
  }
}

// 导出一个新的实例
export default new AxiosService()
